home *** CD-ROM | disk | FTP | other *** search
- i82586_version equ 1
- DAN equ 1
-
- ;
- ; Code that is common between 82586 implementations.
- ;
-
- ; Ported from Tim Krauskopf's micnet.asm, an assembly language
- ; driver for the MICOM-Interlan NI5210, by Russell Nelson. Any bugs
- ; are due to Russell Nelson.
- ; Updated to version 1.08 Feb. 17, 1989 by Russell Nelson.
- ; Updated to support 1500 byte MTU April 27, 1989 By Brad Clements.
-
- ; Copyright, 1988, 1989, Russell Nelson
-
- ; This program is free software; you can redistribute it and/or modify
- ; it under the terms of the GNU General Public License as published by
- ; the Free Software Foundation, version 1.
- ;
- ; This program is distributed in the hope that it will be useful,
- ; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ; GNU General Public License for more details.
- ;
- ; You should have received a copy of the GNU General Public License
- ; along with this program; if not, write to the Free Software
- ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ;
- ; Structure elements specific to the Intel 82586 chip
- ;
- BUF_COUNT EQU 28 ; number of buffers
- XMIT_MTU EQU 1500+14 ; size of xmit buffer (1500 MTU +
- ; 14 bytes for Ethernet headers
-
- SCB EQU BASE_OFFSET + 10 ; system control block base
- CCBPTR EQU BASE_OFFSET + 26 ; offset of configure command block
- TCBPTR EQU BASE_OFFSET + 44 ; xmit CB offset
- TBDPTR EQU BASE_OFFSET + 60 ; xmit BD offset
- TBUFPTR EQU BASE_OFFSET + 68 ; xmit buffer offset
- FDBASE EQU TBUFPTR+XMIT_MTU ; base addr for 30 frame descriptors
- FDSIZE EQU BUF_COUNT * 22
- BDBASE EQU FDBASE+FDSIZE ; base address for 30 buffer descriptors
- BDASIZE EQU BUF_COUNT * 10
- BUFBASE EQU BDBASE+BDASIZE ; base address for 30 200 byte buffers
- BUFFTOP EQU BUFBASE+BUF_COUNT*200
- ISCPTR EQU BASE_OFFSET + 01feeh ; my address for ISCP, points to SCB
- SCPTR EQU BASE_OFFSET + 01ff6h ; hardwired address for SCP
-
- if2
- %out Buffer top is BUFFTOP
- if BUFFTOP gt ISCPTR
- %out Warning, buffers extend beyond ISCPTR, reduce BUF_COUNT.
- endif
- endif
- BDSTAT EQU 0 ; status word in BD
- BDLINK EQU 2 ; 16pointer to next BD
- BDPTR EQU 4 ; 24pointer to actual buffer
- BDSIZE EQU 8 ; size of the buffer
- ;
- SSTAT EQU 0 ; status word for SCB
- SCOM EQU 2 ; command word in SCB
- SCBL EQU 4 ; 16pointer to command block list
- SRFA EQU 6 ; 16pointer to receive frame list
- SERRS EQU 8 ; 4 words of error counts
- ;
- FDSTAT EQU 0 ; status word for frame
- FDEOL EQU 2 ; end of FD list flag
- FDLINK EQU 4 ; 16pointer to next FD
- FDPTR EQU 6 ; 16pointer to list of BD's
- ;
- TSTAT EQU 0 ; status word for xmit
- TCOM EQU 2 ; command to transmit
- TLINK EQU 4 ; 16pointer to next command (always ffff)
- TPTR EQU 6 ; 16pointer to xmit TBD
- TTRIES EQU 8 ; number of transmit retries
- ;
- MCSTAT equ 0 ; status word for multicast
- MCCOM equ 2 ; command to setup multicast
- MCLINK equ 4 ; 16pointer to next command (always ffff)
- MCCNT equ 6 ; number of multicast addresses.
-
- public rcv_modes
- rcv_modes dw 7 ;number of receive modes in our table.
- dw 0 ;There is no mode zero
- dw 0
- dw rcv_mode_2
- dw rcv_mode_3
- dw rcv_mode_4 ;haven't set up perfect filtering yet.
- dw 0
- dw rcv_mode_6
-
- firstfd dw FDBASE ; start of FD queue
- lastfd dw 0 ; end of the FD chain
- lastbd dw 0 ; end of the BD chain
- flag dw 0
-
-
- ;
- ; Configuration block for 82586, this comprises one config command
- ; Parameters taken from MICOM driver
- ;
- CBCONF DW 0 ; status word
- DW 8002H ; end of command list + configure command
- DW 0ffffh ; link to next command (not used)
- DW 080CH ; fifo=8, byte count=C
- DW 2E00H ; important! Addr (AL) not inserted on the fly!
- DW 6000H ; IFS = 60h
- DW 0F200H ; retry=F, slot time=200h
- CBCONF_FLAGS label byte
- DW 0 ; flags, set to 1 for promiscuous
- CBCONF_MINLEN label byte
- DW 40H ; min frame length=40h
-
-
- include timeout.asm
-
- public as_send_pkt
- ; The Asynchronous Transmit Packet routine.
- ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
- ; interrupts possibly enabled.
- ; Exit with nc if ok, or else cy if error, dh set to error number.
- ; es:di and interrupt enable flag preserved on exit.
- as_send_pkt:
- ret
-
- public drop_pkt
- ; Drop a packet from the queue.
- ; Enter with es:di -> iocb.
- drop_pkt:
- assume ds:nothing
- ret
-
- public xmit
- ; Process a transmit interrupt with the least possible latency to achieve
- ; back-to-back packet transmissions.
- ; May only use ax and dx.
- xmit:
- assume ds:nothing
- ret
-
-
- public send_pkt
- send_pkt:
- ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
- ; (only if the high-performance bit is set in driver_function)
- ;enter with ds:si -> packet, cx = packet length.
- ;exit with nc if ok, or else cy if error, dh set to error number.
- assume ds:nothing
- mov es,base_addr ; base for board
-
- mov word ptr es:[SCB+SCBL],TCBPTR; say where xmit command is
-
- cmp cx,XMIT_MTU ; Is this packet too large?
- ja send_pkt_toobig
-
- mov dx,cx ; save a copy, might be less than 60, ok
-
- cmp dx,RUNT ; minimum length for Ether
- jnb oklen
- mov dx,RUNT ; make sure size at least RUNT
- oklen:
- mov di,TBUFPTR ; start of xmit buffer
-
- ;
- ; check for previous xmit
- ;
- xwait:
- mov bx,word ptr es:[SCB+SCOM] ; is command zeroed yet?
- or bx,bx
- jnz xwait ; not there yet, wait for it
- ;
- ; move the data using word moves.
- ;
- call movemem
- ;
- ; put the correct size into the TBD
- ;
- or dx,08000h ; end of frame bit flag
- mov word ptr es:[TBDPTR],dx ; store it
- mov word ptr es:[TCBPTR],0 ; zero status wd
- mov word ptr es:[TCBPTR+TCOM],08004h; xmit command in TCB
- mov word ptr es:[SCB+SCOM],0100h ; execute command
-
- call doca
-
- clc
- ret
- send_pkt_toobig:
- mov dh,NO_SPACE
- stc
- ret
-
-
- include movemem.asm
-
- public get_address
- get_address:
- ;get the address of the interface.
- ;enter with es:di -> place to get the address, cx = size of address buffer.
- ;exit with nc, cx = actual size of address, or cy if buffer not big enough.
- assume ds:code
- cmp cx,EADDR_LEN ;make sure that we have enough room.
- jb get_address_2
- mov cx,EADDR_LEN
- mov dx,io_addr ; Get our IO base address.
- cld
- get_address_1:
- in al,dx ; get a byte of the eprom address
- stosb ; put it away
- add dx,GET_ADDR_INC ; next register
- loop get_address_1 ; go back for rest
- mov cx,EADDR_LEN
- clc
- ret
- get_address_2:
- stc
- ret
-
-
- rcv_mode_2:
- and CBCONF_FLAGS,not 3
- or CBCONF_FLAGS,2 ;disable broadcasts.
- mov CBCONF_MINLEN,40h
- jmp short reconfigure
- rcv_mode_4:
- rcv_mode_3:
- and CBCONF_FLAGS,not 3 ;clear promiscuous mode.
- mov CBCONF_MINLEN,40h
- jmp short reconfigure
- rcv_mode_6:
- and CBCONF_FLAGS,not 3
- or CBCONF_FLAGS,1 ;set promiscuous mode.
- mov CBCONF_MINLEN,0 ;allow runts.
- reconfigure:
- mov es,base_addr ;get the base address for the board.
- mov si,offset CBCONF ; configure command
- mov di,CCBPTR ; where command will reside
- mov cx,9
- rep movsw ; copy to board
- ;
- ; issue the configure command
- ;
- mov word ptr es:[SCB+SCOM],0100h ; do-command command
- mov word ptr es:[SCB+SCBL],CCBPTR ; where conf command is
- mov word ptr es:[SCB+SERRS],0 ; zero errs field
- mov word ptr es:[SCB+SERRS+2],0 ; zero errs field
- mov word ptr es:[SCB+SERRS+4],0 ; zero errs field
- mov word ptr es:[SCB+SERRS+6],0 ; zero errs field
- call doca
- mov ax,18
- call set_timeout
- reconfigure_1:
- mov ax,word ptr es:[CCBPTR] ; get status word
- test ax,08000h ; is command complete?
- jnz reconfigure_2 ; we're okay.
- call do_timeout ;did we time out yet?
- jne reconfigure_1 ;not yet.
- stc ;timeout -- uh-oh.
- ret
- reconfigure_2:
- clc
- ret
-
-
- public set_multicast_list
- set_multicast_list:
- ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
- ;return nc if we set all of them, or cy,dh=error if we didn't.
- assume ds:code
- mov es,base_addr
- mov word ptr es:[SCB+SCBL],TBUFPTR ;use the transmit buffer.
-
- mov es:[TBUFPTR+MCSTAT],word ptr 0 ;status word
- mov es:[TBUFPTR+MCCOM],word ptr 08003h ;command word for mc-setup + EL
- mov es:[TBUFPTR+MCLINK],word ptr -1 ;no command link.
- mov di,TBUFPTR+MCCNT
- mov ax,cx ;store the count.
- stosw
- rep movsb
-
- call doca
- mov ax,18
- call set_timeout
- set_multicast_1:
- mov ax,word ptr es:[TBUFPTR+MCSTAT] ; get status word
- test ax,08000h ; is command complete?
- jnz set_multicast_2 ; we're okay.
- call do_timeout ;did we time out yet?
- jne set_multicast_1 ;not yet.
- mov dh,NO_MULTICAST ;for some reason we can't do multi's.
- stc
- ret
- set_multicast_2:
- clc
- ret
-
-
- public terminate
- terminate:
- assume ds:code
- ret
-
- public reset_interface
- reset_interface:
- ;reset the interface.
- ;we don't do anything.
- assume ds:nothing
- ret
-
-
- ;called when we want to determine what to do with a received packet.
- ;enter with cx = packet length, es:di -> packet type.
- extrn recv_find: near
-
- ;called after we have copied the packet into the buffer.
- ;enter with ds:si ->the packet, cx = length of the packet.
- extrn recv_copy: near
-
- extrn count_in_err: near
- extrn count_out_err: near
-
- public recv
- recv:
- mov flag, 1
- ;called from the recv isr. All registers have been saved, and ds=cs.
- ;Upon exit, the interrupt will be acknowledged.
- recv1:
- mov ds,base_addr ; base for board
- assume ds:nothing
-
- mov ax,ds:[SCB+SSTAT] ;get the status.
- recv_isr_1:
- cmp word ptr ds:[SCB+SCOM],0 ;are we done yet?
- jne recv_isr_1 ;no -- keep waiting.
-
- and ax,0f000h ;isolate the ACK bits.
- if DAN
- jz recv_isr_2
- endif
- mov ds:[SCB+SCOM],ax ;make a command to
- ;acknowledge the interrupt.
- call doca
- recv_isr_2:
- cmp word ptr ds:[SCB+SCOM],0 ;are we done yet?
- jne recv_isr_2 ;no -- keep waiting.
-
- ; Get whatever packets are on the board
- ;
- mov bx,firstfd ; get addr of first FD in list
- mov ax,[bx+FDSTAT] ; status word of frame
- test ax,08000h ; frame written?
- jnz okframe
-
- jmp ru_start ; no, restore receiver if necessary
- frame_bad:
- call count_in_err
- ptrupdate_j_1:
- jmp ptrupdate
-
- ; we have a frame, read it in
- ;
- okframe:
- test ax,02000h ;check frame OK bit
- jz frame_bad ;bad, fix it.
- mov si,[bx+FDPTR] ;get pointer to buffer descriptor
- xor cx,cx ;start with zero bytes.
- countbuf: ;es:di is already set to receive packet
- mov dx,si ;save a copy of current BD ptr
- mov ax,[si+BDSTAT] ;get status and count word for BD
- test ax,04000h ;is count field there?
- jz ptrupdate_j_1 ;no - we give up here.
- add cl,al ;add the count into cx.
- adc ch,0
- mov si,[si+BDLINK] ;go to next BD in list
- test ax,8000h ;is this the last frame?
- je countbuf ;no - keep counting.
-
- push bx
- push cx
-
- mov ax,cs ;we need ds = code.
- mov ds,ax
- assume ds:code
-
- mov es,base_addr ;get a pointer to their type.
- mov di,es:[bx+FDPTR] ;get pointer to buffer descriptor
- mov di,es:[di+BDPTR] ;get offset of data
- add di,EADDR_LEN+EADDR_LEN ;skip the ethernet addreses and
- ; point to the packet type.
-
- call recv_find ;look up our type.
-
- pop cx
- pop bx
- mov ds,base_addr ;restore ds to the board.
- assume ds:nothing
-
- mov ax,es ;is this pointer null?
- or ax,di
- je ptrupdate ;yes - just free the frame.
-
- push cx
- push es ;remember where the buffer pointer is.
- push di
- if DAN
- push cx
- endif
-
- mov si,[bx+FDPTR] ;get pointer to buffer descriptor
- copybuf:
- mov dx,si ;save a copy of current BD ptr
- xor ch,ch ;200 bytes is largest this can be
- mov cl,[si+BDSTAT] ;get count word for BD
- mov si,[si+BDPTR] ;get offset of data
- if DAN
- pop ax
- sub ax, cx
- jc copydone
- push ax
- ENDIf
- call movemem
- mov si,dx ;get back current BD ptr
- test [si+BDSTAT],8000h ;check EOF bit
- mov si,[si+BDLINK] ;go to next BD in list
- jz copybuf ;not done, keep copying it.
-
- if DAN
- pop cx
- copydone:
- endif
- pop si ;now give the frame to the client.
- pop ds
- pop cx
- assume ds:nothing
-
- call recv_copy
- ;
- ; we are done with the frame, do the list management
- ;
- ptrupdate:
- push cs
- pop ds
- assume ds:code
- mov es,base_addr ; reload board segment
-
- mov si,es:[bx+FDPTR] ; first BD in frame list
- nextbd:
- mov cx,es:[si+BDSTAT] ; count word for BD, EOF bit
- test cx,08000h ; EOF bit, if set, save si in lastbd
- jnz dolastbd
- mov word ptr es:[si+BDSTAT],0 ; clear status word, EOF bit
- cmp si,lastbd ; see if we are wrapping
- jz dolastbd ; yes, just undo it
- mov si,es:[si+BDLINK] ; follow link
- jmp nextbd
- dolastbd:
- mov di,lastbd ; where end of BD list is now
- mov lastbd,si ; store last known BD
- mov word ptr es:[si+BDSIZE],08000h+200 ; end of list here
- mov word ptr es:[si+BDSTAT],0 ; clear status word, EOF bit
- ; size field for not end of list
- mov word ptr es:[di+BDSIZE],200 ; remove old end-of-list
-
- ;
- ; update the FD list flags, new end-of-list
- ;
- mov word ptr es:[bx+FDEOL],08000h ; store new EOL
- mov word ptr es:[bx+FDSTAT],0 ; clear status word for frame
- mov di,lastfd ; get old end-of-list
- mov word ptr es:[di+FDEOL],0 ; zero old one
- mov lastfd,bx ; update stored pointer
- mov si,es:[bx+FDLINK] ; where next fd is
- mov firstfd,si ; store that info for next time
- if DAN
- jmp recv1
- endif
-
- ru_start:
- ; re-start receive unit
- ;
- ; check to see if the receiver went off because of no resources
- ; and restart receiver if necessary
- ;
- push cs
- pop ds
- mov es,base_addr
- mov ax,es:[SCB+SSTAT] ; status word for SCB
- and ax,070h ; receiver status
- cmp al,020h ; receiver has no resources
- jnz hasres
- if DAN
- cmp flag, 1
- jnz ru_start1
- mov flag, 0
- jmp recv1
- endif
-
- ru_start1:
- call count_out_err
- ;
- ; setup lists for starting the RU on the chip
- ; we know that there isn't anything in the buffer that we want
- ;
-
- mov bx,firstfd ; get first FD on free list (assume free)
- mov word ptr es:[SCB+SRFA],bx ; put into SCB
- mov si,lastbd ; pointer to a BD, end of chain
- mov ax,word ptr es:[si+BDLINK] ; pointer to next BD
- mov word ptr es:[bx+FDPTR],ax ; set to start of BDs
- ;
- ;
- ; Start the RU, doesn't need CB, only SCB parms.
- ; command, to start receiving again
- ;
- mov word ptr es:[SCB+SSTAT],0 ; clear status word
- mov word ptr es:[SCB+SCOM],010h ; start RU
- call doca
- hasres:
- recv_isr_end:
- cmp word ptr es:[SCB+SCOM],0 ;are we done yet?
- jne recv_isr_end ;no -- keep waiting.
- ret
-
-
- public recv_exiting
- recv_exiting:
- ;called from the recv isr after interrupts have been acknowledged.
- ;Only ds and ax have been saved.
- assume ds:nothing
- ret
-
-
- public set_address
- set_address:
- assume ds:nothing
- ;enter with ds:si -> Ethernet address, CX = length of address.
- ;exit with nc if okay, or cy, dh=error if any errors.
- cmp cx,EADDR_LEN ;ensure that their address is okay.
- je set_address_4
- mov dh,BAD_ADDRESS
- stc
- jmp short set_address_done
- set_address_4:
-
- ; Next step, load our address into the board
- ; reuses the space that the configure command used, with different command
- ;
- mov es,base_addr ; set to base address
- mov word ptr es:[SCB+SCBL],CCBPTR ; say where conf command is
-
- mov di,CCBPTR ; start of config command block
- xor ax,ax
- stosw ; zero status word for commmand
- mov ax,8001h ; IA setup command + EL
- stosw
- xor ax,ax
- dec ax
- stosw ; set link value to -1 (unused)
-
- rep movsb ; move their ethernet address in.
- ;
- ; start the IA setup command
- ;
- mov word ptr es:[SCB+SCOM],0100h ; do-command command
- call doca
- xor cx,cx ; timeout
- set_address_1:
- mov ax,word ptr es:[CCBPTR] ; get status word
- test ax,08000h ; is command complete?
- loopz set_address_1
- jnz set_address_okay
- stc
- mov dh,-1 ; no error in the list applies.
- jmp short set_address_done
- set_address_okay:
- mov cx,EADDR_LEN ;return their address length.
- clc
- set_address_done:
- push cs
- pop ds
- assume ds:code
- ret
-
-
- end_resident label byte
-
- timeout_msg db "Timed out while initializing the board.",CR,LF,'$'
- int_no_name db "Interrupt number ",'$'
- io_addr_name db "I/O port ",'$'
- base_addr_name db "Memory address ",'$'
- our_address db 6 dup(?) ;temporarily hold our address
-
- tdr_ok_msg db "TDR Ok",CR,LF,'$'
- tdr_none_msg db "Your Ethernet card doesn't seem to be plugged in.",CR,LF,'$'
- tdr_open_msg db " clocks away is an OPEN",CR,LF,'$'
- tdr_short_msg db " clocks away is a SHORT",CR,LF,'$'
-
- mem8_16 db 2 ; 1 for 16k, 2 for 8k
-
- extrn set_recv_isr: near
- extrn maskint: near
-
- ;enter with si -> argument string, di -> word to store.
- ;if there is no number, don't change the number.
- extrn get_number: near
-
- ;enter with dx -> name of word, di -> dword to print.
- extrn print_number: near
-
- ;enter with ax = number to print.
- extrn decout: near
-
- public parse_args
- parse_args:
- mov di,offset int_no
- call get_number
- mov di,offset io_addr
- call get_number
- mov di,offset base_addr
- call get_number
- sub base_addr,BASE_OFFSET shr 4
- clc
- ret
-
-
- timeout_error:
- mov dx,offset timeout_msg
- jmp short error
- error:
- mov ah,9
- int 21h
- stc
- ret
-
- ;
- ; data for configuring and setting up the board
- ;
- ; chip always looks at SCP for config info which points to ISCP for the
- ; pointer to the CONTROL BLOCK which handles everything from there.
- ; Kind of indirect, but it works.
- ;
- SCP DB 0 ; bus use flag (0=16 bit, 1=8 bit).
- DB 5 DUP(0) ; unused
- DW ISCPTR ; 24pointer to ISCP offset
- DW 0 ; high part
- ;
- ; Intermediate SCP
- ;
- ISCP DW 1 ; busy flag
- DW SCB ; 16pointer to SCB
- DW 0,0 ; base for all 16 pointers, lo, hi
- ; board is hardwired to 0 for these values
- ;
- ; CB for xmit, followed by BD for xmit, copied together
- ;
- TCB DW 0 ; status word
- DW 08004H ; command word for xmit + EL
- DW 0ffffh ; no command link
- DW TBDPTR ; 16pointer to xmit BD
- DW 0,0,0,0 ; no addressing used here
- ;
- ; BD template for xmit
- TBD DW 0
- DW 0 ; next BD pointer, unused
- DW TBUFPTR ; 24pointer to xmit buffer
- DW 0 ; high part of pointer
-
- public etopen
- etopen:
- mov al,int_no
- call maskint ;disable these interrupts.
-
- ; Initialize the Ethernet board, set receive type.
- ;
- ; check for correct EPROM location
- ;
- call check_board
-
- ;
- ; Turn off interrupts, I don't want them
- ;
- ifdef IOINTOF
- loadport
- setport IOINTOF
- out dx,al
- endif
- ;
- ; Disconnect from network
- ;
- ifdef IODIS
- loadport
- setport IODIS
- out dx,al
- endif
-
- ;
- ; Initialize the Ethernet board.
- ;
- mov es,base_addr ; set to base address
-
- ;
- ; Intermediate SCP
- ;
- mov si,offset ISCP ; addr of pre-set values
- mov di,ISCPTR
- mov cx,4 ; 4 words
- rep movsw ; install ISCP
-
- ;
- ; Now discern the end of memory by repeatedly re-initializing the board
- ; until the BUSY flag in the ISCP gets reset.
- ;
- mov di,SCPTR
-
- re_discern:
- push di
- mov si,offset SCP ; get pre-set values
- mov cx,5 ; 5 words
- rep movsw ; install SCP
- pop di
-
- ifdef IORESET
- ;
- ; Reset the chip
- ;
- loadport
- setport IORESET
- out dx,al
- endif
- ;
- ; Issue a CA to initialize the chip after reset
- ;
- call lbca
-
- mov ax,2 ;don't wait too long.
- call set_timeout
- confwait:
- cmp byte ptr es:[ISCPTR],0 ;did it clear the busy flag?
- je confok ;yes.
- call do_timeout
- jne confwait
-
- add di,2000h ;go up another 8K.
- jnc re_discern ;try this next higher address.
- confbad:
- sti
- jmp timeout_error
-
- confok:
- call reconfigure
- jc confbad
-
- ;
- ; Ask the board for the Ethernet address, and then use set_address to set it.
- ;
- push ds
- pop es
- mov di,offset our_address
- mov cx,EADDR_LEN
- call get_address
-
- mov si,offset our_address
- mov cx,EADDR_LEN
- call set_address
- jnc store_address_2
- sti
- jmp timeout_error
- store_address_2:
- ;
- ; IA sent, setup all of the other data structures on the board
- ; start with xmit command descriptors
- ;
- mov si,offset TCB ; template for xmit
- mov di,TCBPTR ; where it goes on board
- mov cx,12 ; copies CB and BD for xmit
- rep movsw
- ;
- ; Set up frame and buffer descriptors, 30 each
- ;
- mov cx,BUF_COUNT ; # of FDs
- mov di,FDBASE ; base addr for FDs
- fdloop:
- xor ax,ax
- mov bx,di ; save pointer
- stosw ; clear status wd
- stosw ; clear EL field
- add bx,22 ; points to next one
- mov es:[di],bx ; put in link ptr
- inc di
- inc di
- dec ax
- stosw ; clear BD ptr to -1
- add di,14
- loop fdloop
-
- sub di,20 ; point back to last EL field
- mov ax,08000h ; end of list
- stosw ; put into last FD
- sub di,4 ; back to beginning of last FD
- mov lastfd,di ; save the pointer
- mov word ptr es:[di+FDLINK],FDBASE ; make list circular,
- ; from last to first
-
- mov ax,BDBASE ; first BD
- mov word ptr es:[FDBASE+FDPTR],ax ; put it in the first FD frame
- ;
- ; now BDs
- mov cx,BUF_COUNT
- mov di,BDBASE ; start of BD area
- mov dx,BUFBASE ; start of buffer area
- bdloop:
- xor ax,ax
- mov bx,di ; save pointer
- stosw ; zero status field
- add bx,10 ; point to next record
- mov es:[di],bx ; put in link ptr
- inc di
- inc di
- mov es:[di],dx ; address of buffer, lo part
- inc di
- inc di
- stosw ; zero out high part
- mov ax,200
- stosw ; store length field
- add dx,ax ; add in length of buffer, updates ptr
- loop bdloop
-
- sub di,2 ; back to last BD size field
- mov ax,08000h+200 ; end of list + 200
- stosw ; mark end of list
- sub di,8 ; back to last BDLINK field
- mov ax,BDBASE
- stosw ; put link to beginning of list here
- sub di,4 ; back to beginning of last BD
- mov lastbd,di ; save pointer to end of list
- ifdef IOENA
- ;
- ; configure to connect to network
- ;
- loadport
- setport IOENA ; enable network
- out dx,al ; any al value
- endif
- ;
- ; Test to see if the network is okay.
- ;
- mov di,CCBPTR ; start of config command block
- xor ax,ax ; zero status word for commmand
- stosw
- mov ax,8005h ; TDR command + EL
- stosw
- xor ax,ax
- dec ax
- stosw ; set link value to -1 (unused)
- inc ax
- stosw ; zero time result.
-
- mov word ptr es:[SCB+SCOM],0100h ; do-command command
-
- call lbca
-
- xor cx,cx ; timeout
- do_tdr_1:
- mov ax,word ptr es:[CCBPTR] ; get status word
- test ax,08000h ; is command complete?
- loopz do_tdr_1
- mov ax,word ptr es:[CCBPTR+6]
- jnz do_tdr_2
- mov ax,2000h ; treat a timeout as an open
- do_tdr_2:
- test ax,8000h
- mov dx,offset tdr_ok_msg
- jne do_tdr_3
- mov dx,offset tdr_short_msg
- test ax,2000h
- je do_tdr_4
- mov dx,offset tdr_none_msg
- cmp ax,2000h
- je do_tdr_3
- mov dx,offset tdr_open_msg
- do_tdr_4:
- push dx
- and ax,2048-1
- xor dx,dx
- call decout
- pop dx
- do_tdr_3:
- mov ah,9
- int 21h
-
- ;
- ; Start the RU, doesn't need CB, only SCB parms.
- ; command, to start receiving
- ;
- mov word ptr es:[SCB+SSTAT],0 ; clear status word
- mov word ptr es:[SCB+SRFA],FDBASE ; set to frame descriptors
- mov word ptr es:[SCB+SCOM],010h ; start RU
- call lbca
- ;
- ; Now reset CX, FR, CNA, and RNR so that we don't get a spurious interrupt.
- ;
- store_ack_1:
- cmp word ptr es:[SCB+SCOM],0 ;are we done yet?
- jne store_ack_1 ;no -- keep waiting.
-
- mov ax,es:[SCB+SSTAT] ;get the status.
- and ax,0f000h ;isolate the ACK bits.
- mov es:[SCB+SCOM],ax ;make a command to
- ;acknowledge the interrupt.
- call doca
- ;
- ; Now hook in our interrupt
- ;
- call set_recv_isr
-
- sti
-
- mov al, int_no ; Get board's interrupt vector
- add al, 8
- cmp al, 8+8 ; Is it a slave 8259 interrupt?
- jb set_int_num ; No.
- add al, 70h - 8 - 8 ; Map it to the real interrupt.
- set_int_num:
- xor ah, ah ; Clear high byte
- mov int_num, ax ; Set parameter_list int num.
-
- mov dx,offset end_resident
- clc
- ret
-
- public print_parameters
- print_parameters:
- mov di,offset int_no
- mov dx,offset int_no_name
- call print_number
- mov di,offset io_addr
- mov dx,offset io_addr_name
- call print_number
- mov di,offset base_addr
- mov dx,offset base_addr_name
- call print_number
- ret
-